package com.piece.core.message.client.impl;

import com.piece.core.framework.exception.ErrorCode;
import com.piece.core.framework.support.bootstrap.DataTable;
import com.piece.core.framework.support.response.AjaxResponse;
import com.piece.core.framework.util.collection.MapUtil;
import com.piece.core.framework.util.math.SequenceUtil;
import com.piece.core.framework.util.net.HttpUtil;
import com.piece.core.framework.util.security.SecurityUtil;
import com.piece.core.framework.util.string.JsonUtil;
import com.piece.core.framework.util.time.DateUtil;
import com.piece.core.log.client.LogFactory;
import com.piece.core.message.client.dto.SmsReceiveRespDTO;
import com.piece.core.message.client.dto.SmsSendRespDTO;
import com.piece.core.message.client.dto.SmsTemplateRespDTO;
import com.piece.core.message.enums.AuditStatusType;
import com.piece.core.message.properties.SmsProperties;
import org.apache.commons.collections.map.LinkedMap;
import org.springframework.util.Assert;
import java.util.*;

/**
 * 基于钉钉 WebHook 实现的短信客户端实现类
 */
public class DingTalkSmsClient extends AbstractSmsClient {

    public DingTalkSmsClient(String applicationName, SmsProperties properties, LogFactory auditLogFactory) {
        super(applicationName, properties, auditLogFactory);
        Assert.notEmpty(new Object[]{ properties.getApiKey() }, "apiKey 不能为空");
        Assert.notEmpty(new Object[]{ properties.getApiSecret() }, "apiSecret 不能为空");
    }

    @Override
    protected void doInit() {
    }

    @Override
    protected AjaxResponse doSendSms(String logId, String mobile, String apiTemplateId, LinkedMap templateParams) throws Exception {
        String url = buildUrl("robot/send");
        Map<String, Object> params = new HashMap<>();
        params.put("msgtype", "text");
        String content = String.format("【模拟短信】\n手机号：%s\n短信日志编号：%d\n模板参数：%s",
                mobile, logId, JsonUtil.toJson(templateParams));
        Map<String, String> text_map = new HashMap<>();
        text_map.put("content", content);
        params.put("text", text_map);
        // 执行请求
        String responseText = HttpUtil.post(url).data(JsonUtil.toJson(params)).execute().text();
        // 解析结果
        Map responseObj = JsonUtil.toMap(responseText);
        String code = MapUtil.getString("errcode", responseObj);
        String message = MapUtil.getString("errmsg", responseObj);
        return AjaxResponse.result(convert(code, message), SmsSendRespDTO.builder()
                        .bizId(SequenceUtil.uuid())
                        .outId(logId)
                        .content(content)
                        .receiveDate(DateUtil.formatDate(new Date(), DateUtil.FORMAT_YYYY_MM_DD_HH_MM_SS))
                        .build());
    }

    /**
     * 构建请求地址
     *
     * 参见 https://developers.dingtalk.com/document/app/custom-robot-access/title-nfv-794-g71 文档
     */
    private String buildUrl(String path) throws Exception {
        // 生成 timestamp
        long timestamp = System.currentTimeMillis();
        // 生成 sign
        String secret = properties.getApiSecret();
        String stringToSign = timestamp + "\n" + secret;
        String sign = SecurityUtil.encryptHMAC("HmacSHA256", stringToSign, secret);
        // 构建最终 URL
        return String.format("https://oapi.dingtalk.com/%s?access_token=%s&timestamp=%d&sign=%s",
                path, properties.getApiKey(), timestamp, sign);
    }

    @Override
    protected List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) {
        throw new UnsupportedOperationException("模拟短信客户端，暂时无需解析回调");
    }

    @Override
    protected AjaxResponse doGetSmsTemplate(String apiTemplateId) {
        SmsTemplateRespDTO data = SmsTemplateRespDTO.builder()
                .id(apiTemplateId)
                .content("")
                .auditStatus(AuditStatusType.SUCCESS.getStatus())
                .auditReason("")
                .build();
        return AjaxResponse.result(ErrorCode.SUCCESS, data);
    }

    @Override
    public AjaxResponse queryDetail(String mobile, String bizId, int pageIndex, int pageSize) {
        DataTable dataTable = new DataTable();
        dataTable.setStart(pageIndex);
        dataTable.setLength(pageSize);
        dataTable.setRecordsTotal(0);
        dataTable.setData(Collections.EMPTY_LIST);
        return AjaxResponse.result(ErrorCode.SUCCESS, dataTable);
    }

    private ErrorCode convert(String code, String msg) {
        return Objects.equals(code, "0") ? ErrorCode.SUCCESS : new ErrorCode(500, msg);
    }
}